﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using ParkingLot.Entitys.Enums;
using ParkingLot.Entitys.Messages;
using ParkingLot.Utility.Extend;
using ParkingLot.Utility.LogHelps;
using ParkingLot.Utility.SerializeHelp;
using ParkingLot.Utility.SocketHelp;

namespace ParkingLot.Utility.MessageHelp
{
    /// <summary>
    /// 消息 队列
    /// </summary>
    public class MessageAggregator<T>
    {
        private static Action<T> m_MessageAction;

        static MessageAggregator()
        {

            Type type = typeof(MessageAggregator<T>);
            Type parenType = typeof(ICommunicationMessage);
            Type messageType = typeof(T);

            //处理其他进程发送的消息
            if (parenType.IsAssignableFrom(messageType))
            {
                MethodInfo methodInfo = type.GetMethod("DealMessage", BindingFlags.NonPublic | BindingFlags.Static);
                MessageManage.Instance.DcitMethodInfos.Add(messageType.GUID, methodInfo);

            }

        }

        /// <summary>
        /// 订阅消息
        /// </summary>
        /// <param name="action"></param>
        public static void Subscribe(Action<T> action)
        {
            m_MessageAction += action;
        }

        /// <summary>
        /// 取消订阅
        /// </summary>
        /// <param name="action"></param>
        public static void UnSubscribe(Action<T> action)
        {
            m_MessageAction -= action;
        }

        /// <summary>
        /// 推送消息
        /// </summary>
        /// <param name="t"></param>
        public static void Publish(T t, bool IsDeepCopy = false, ProgressCommunication progressCommunication = ProgressCommunication.InnerCommunication,string messageIdGuid="")
        {
            #region 是否深拷贝
            T tInstance;
            if (IsDeepCopy)
            {
                //深拷贝
                tInstance = DeepCopy.DeepCopyByReflect<T>(t);
            }
            else
            {
                //浅拷贝
                tInstance = t;
            }
            #endregion

            switch (progressCommunication)
            {
                case ProgressCommunication.InnerCommunication:
                    DealMessage(tInstance);
                    break;
                case ProgressCommunication.ClientToServer:
                    //客户端到服务器推送消息
                    bool bolCanPublish = CanPublishMessage<T>(tInstance);
                    if (!bolCanPublish)
                    {
                        break;
                    }
                    // 对象序列化后形成的byte流   
                    byte[] csBytes = ByteFlowHelp.SerializeToByteArray(tInstance);
                    //报文头
                    byte[] csHead = MessageManage.Instance.GetHeadBytes(messageIdGuid);
                    //消息体=报文头+对象序列化后形成的byte流
                    byte[] sendBytes = new byte[csBytes.Length + csHead.Length];
                    Buffer.BlockCopy(csHead, 0, sendBytes, 0, csHead.Length);//这种方法仅适用于字节数组
                    Buffer.BlockCopy(csBytes, 0, sendBytes, csHead.Length, csBytes.Length);
                    csHead.CopyTo(sendBytes, 0);
                    csBytes.CopyTo(sendBytes, csHead.Length);
                    //以byte流的方式推送数据
                    SendHelp.StartFirmSend(MessageManage.Instance.ClientToServerIP,
                        MessageManage.Instance.ClientToServerPort, sendBytes);
                    break;
                case ProgressCommunication.ServerToClient:
                    /*服务端到客户端推送消息*/
                    //判断对象能否被推送
                    bool bolCanPublishMesssage = CanPublishMessage<T>(tInstance);
                    if (!bolCanPublishMesssage)
                    {
                        break;
                    }
                    // 对象序列化后形成的byte流   
                    byte[] bytes = ByteFlowHelp.SerializeToByteArray(tInstance);
                    //报文头
                    byte[] head =MessageManage.Instance.GetHeadBytes(messageIdGuid);
                    //消息体=报文头+对象序列化后形成的byte流
                    byte[] lastvalue = new byte[bytes.Length + head.Length];
                    Buffer.BlockCopy(head, 0, lastvalue, 0, head.Length);//这种方法仅适用于字节数组
                    Buffer.BlockCopy(bytes, 0, lastvalue, head.Length, bytes.Length);
                    head.CopyTo(lastvalue, 0);
                    bytes.CopyTo(lastvalue, head.Length);
                    //以byte流的方式推送数据
                    SendHelp.StartFirmSend(MessageManage.Instance.ServerToClientIP,
                        MessageManage.Instance.ServerToClientPort, lastvalue);
                    break;
            }
            
        }

       

        /// <summary>
        /// 能否发送消息
        /// </summary>
        /// <returns></returns>
        private static bool CanPublishMessage<T>(T t)
        {
            Type type = t.GetType();

            //能否序列化
            bool bolCanSerialize = SerializableHelp.IsCanSerializable(type);
            if (!bolCanSerialize)
            {
                LogEncity logEncity = new LogEncity()
                {
                    LogTime = DateTime.MinValue.GetCurTime(),
                    LogType = LogType.Error,
                    Message = $"{type.FullName}  {Warning.Instance.SerializableWarn}",
                };
                LogHelp.AddLog(logEncity);
                return false;
            }
            return true;
        }

        /// <summary>
        /// 处理接收的数据(不能删,不能重命名，虽然没有引用,通过反射访问这个方法)
        /// </summary>
        /// <param name="t"></param>
        private static void DealMessage(T t)
        {
            if (m_MessageAction != null)
            {
                m_MessageAction.Invoke(t);
            }
        }
    }


}
